#include "protos/user_service.grpc.pb.h"

#include "common/config.hpp"
#include "database/db_connection.hpp"
#include "database/user_dao.hpp"
#include "models/user.hpp"
#include "utils/token.hpp"
#include "utils/crypto.hpp"

#include <iostream>
#include <string>
#include <memory>
#include <chrono>
#include <grpc++/grpc++.h>

#include <workflow/WFFacilities.h>
#include <ppconsul/agent.h>

using namespace cloud::storage;
   
ppconsul::agent::Agent* g_consul_agent = nullptr;
std::string g_service_id = "user-service-instance-1";

class UserServiceImpl final : public UserService::Service {
public:
    // 实现注册 RPC 方法
    grpc::Status Signup(grpc::ServerContext* context, const SignupRequest* request, SignupResponse* response) override {
        std::string username = request->username();
        std::string password = request->password();

        if (username.empty() || password.empty()) {
            response->set_code(1);
            response->set_message("Username or password cannot be empty.");
            return grpc::Status::OK;
        }

        if (UserDao::userExists(username)) {
            response->set_code(2);
            response->set_message("Username already exists.");
            return grpc::Status::OK;
        }

        User user;
        user.username = username;
        user.salt = Crypto::generateSalt();
        user.password = Crypto::hashPassword(password, user.salt);
        
        if (UserDao::createUser(user)) {
            response->set_code(0);
            response->set_message("User registered successfully.");
        } else {
            response->set_code(3);
            response->set_message("Failed to create user in database.");
        }
        return grpc::Status::OK;
    }

    // 实现登录 RPC 方法
    grpc::Status Signin(grpc::ServerContext* context, const SigninRequest* request, SigninResponse* response) override {
        std::string username = request->username();
        std::string password = request->password();

        auto user_opt = UserDao::getUserByUsername(username);
        if (!user_opt.has_value()) {
            response->set_code(1);
            response->set_message("Invalid username or password.");
            return grpc::Status::OK;
        }

        if (Crypto::verifyPassword(password, user_opt->salt, user_opt->password)) {
            std::string token = Token::generate(username);
            response->set_code(0);
            response->set_message("Signin successful.");
            response->set_token(token);
        } else {
            response->set_code(1);
            response->set_message("Invalid username or password.");
        }
        return grpc::Status::OK;
    }
    
    // 实现获取用户信息 RPC 方法
    grpc::Status GetUserInfo(grpc::ServerContext* context, const UserInfoRequest* request, UserInfoResponse* response) override {
        std::string token = request->token();
        std::string username = Token::extractUsername(token);

        if (username.empty()) {
            response->set_code(1);
            response->set_message("Invalid or expired token.");
            return grpc::Status::OK;
        }

        auto user_opt = UserDao::getUserByUsername(username);
        if (!user_opt.has_value()) {
            response->set_code(2);
            response->set_message("User not found.");
            return grpc::Status::OK;
        }

        response->set_code(0);
        response->set_message("Success");
        response->set_username(user_opt->username);
        response->set_signup_at(user_opt->created_at);
        return grpc::Status::OK;
    }
};


// 心跳回调函数
void heartbeat_callback(WFTimerTask *task) {
    if (g_consul_agent) {
        try {
            // 直接使用全局的 agent 对象
            g_consul_agent->servicePass(g_service_id);
        } catch (const std::exception& e) {
            fprintf(stderr, "[Heartbeat] ERROR for UserService: %s\n", e.what());
        }
    }
    // 创建下一个定时器任务，形成循环
    series_of(task)->push_back(WFTaskFactory::create_timer_task(7, 0, heartbeat_callback));
}


// 封装了启动服务器和注册服务的逻辑
void RunServer() {
    std::string server_address("0.0.0.0:50051"); // 服务监听地址和端口
    UserServiceImpl service_impl;

    grpc::ServerBuilder builder;
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service_impl);

    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    if (server == nullptr) {
        std::cerr << "Fatal: Failed to start UserService." << std::endl;
        return;
    }
    std::cout << "UserService listening on " << server_address << std::endl;

    // --- 使用 ppconsul 进行服务注册 ---
    try {
        static ppconsul::Consul consul(Config::CONSUL_URI);
        g_consul_agent = new ppconsul::agent::Agent(consul);
        g_consul_agent->registerService(
            ppconsul::agent::kw::id = g_service_id,
            ppconsul::agent::kw::name = "UserService",
            ppconsul::agent::kw::address = "127.0.0.1",
            ppconsul::agent::kw::port = 50051,
            ppconsul::agent::kw::check = ppconsul::agent::TtlCheck(std::chrono::seconds{15})
        );
        std::cout << "[Registry] Service 'UserService' registered to Consul." << std::endl;

        // --- 启动心跳 ---
        WFTimerTask *timer = WFTaskFactory::create_timer_task(7, 0, heartbeat_callback);
        timer->start();
        std::cout << "[Heartbeat] Heartbeat started for " << g_service_id << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "[Registry] ERROR: Failed to register to Consul. Reason: " << e.what() << std::endl;
    }

    // 阻塞主线程，等待服务器被终止
    server->Wait();
}

int main(int argc, char** argv) {
    // 1. 加载全局配置
    if (!Config::load()) {
        std::cerr << "Fatal: Failed to load config/app.conf" << std::endl;
        return 1;
    }
    // 2. 初始化数据库连接
    if (!DBConnection::getInstance()->connect()) {
        std::cerr << "Fatal: Failed to connect to database" << std::endl;
        return 1;
    }
    // 3. 运行 gRPC 服务器
    RunServer();

    return 0;
}
